from datetime import datetime

# 流水登记的时间
# 文件：bank_info.txt  / bank_{user}_flow.txt
# bank_info.txt : 用户-登录密码-银行卡号-取款密码-余额（初始定为1000）
# bank_{user}_flow : {user}>>>操作>>>时间
# 取款 :  验证你的取款密码，更改余额   余额(1000) ，记录你的提款信息 -- 文件里 - 加时间
# 转账 ： 验证你的取款密码，更改余额 目标银行卡号去转 记录你的提款信息 -- 文件里

# time = f'时间为:>>>> {datetime.now().strftime("%Y年%m月%d日 %H时%M分%S秒")}'

login_user_dict = {'username': '',
                   "bank_id": '',
                   "bank_pay_pwd": "",
                   "balance": 0
                   }  # 登录情况收集

ABSOLUTE_PATH = r'D:\Files\Python\ATM系统\ATM-Data\\'


# 收集用户名和密码，并返回username,password
def get_name_pwd():
    username = input("用户名：").strip()
    password = input("密码：").strip()
    return username, password


def register():
    print("注册系统".center(50, '-'))
    username, password = get_name_pwd()
    check_info(username=username, password=password)
    flag, msg = save_data('pwd', username=username, password=password)
    if flag:
        txt = f"{username}注册成功"
        print(txt)
        save_flow('login', user=username, txt=f"{txt}>>>时间为{datetime.now().strftime('%Y年%m月%d日 %H时%M分%S秒')}")
    return flag, msg


# 检查信息的规范性
def check_info(*args, **kwargs):
    username = kwargs.get('username')
    bank_id_pwd = ''
    balance = ''
    while True:
        print("信息录入".center(10, '>'))
        bank_id = input("请输入银行卡号(4位数字)：").strip()
        if not bank_id.isdigit():
            print("银行卡号不可以出现非法字符！")
            continue
        elif len(bank_id) != 4:
            print("银行卡号必须4个字符！")
            continue
        bank_id_pwd = input("请输入取款密码(4位密码)：").strip()
        if len(bank_id_pwd) > 4:
            print("请不要输入超过4个字符！")
            continue
        balance = 1000  # 默认注册时为1000
        break
    save_data('info', username=username, bank_id=bank_id, pay_pwd=bank_id_pwd, balance=balance)


# 创造保存的数据并将数据传入save_file函数
def save_data(*args, **kwargs):
    save_dict = '|'.join([str(value) for value in kwargs.values()])
    print(save_dict)
    if args[0] == 'info':
        flag, msg = save_file(path='all_info.txt', data=save_dict)
        return flag, msg
    elif args[0] == 'pwd':
        flag, msg = save_file(path='all_pwd.txt', data=save_dict)
        return flag, msg


# 将传入的数据写入文件
def save_file(path, data):
    try:
        with open(f"{ABSOLUTE_PATH}{path}", 'a') as fp:
            fp.write(data + '\n')
            fp.flush()
            return True, "文件写入成功！"
    except Exception as e:
        return False, f"文件写入失败，错误信息：{e}"


# 读取数据
def read_data(tag, path):
    try:
        with open(f"{ABSOLUTE_PATH}{path}", 'r', encoding='utf8') as fp:
            data = fp.read().split('\n')
            data_dict = {}
            for i in data:
                if i == '':
                    continue
                if tag == 'info':
                    username, bank_id, pay_pwd, balance = i.split('|')
                    data_dict[username] = {'id': bank_id, 'pay_pwd': pay_pwd, 'balance': int(balance)}
                elif tag == 'pwd':
                    username, password = i.split('|')
                    data_dict[username] = {'pwd': password}
            return data_dict
    except Exception as e:
        return f"文件读取失败，错误信息是{e}"


def login():
    username, password = get_name_pwd()
    flag, msg = check_login(username=username, password=password)
    if flag:
        init_login_dict(user=username)
    return flag, msg


# 将登录用户信息填入至全局名称空间的字典中
def init_login_dict(user):
    data_dict = read_data('info', 'all_info.txt')
    login_dict = data_dict[user]
    login_user_dict['username'] = user
    login_user_dict['bank_id'] = login_dict['id']
    login_user_dict['bank_pay_pwd'] = login_dict['pay_pwd']
    login_user_dict['balance'] = int(login_dict['balance'])


# 校验用户名和密码
def check_login(*args, **kwargs):
    username, password = kwargs.get('username'), kwargs.get('password')
    data_dict = read_data(tag='pwd', path='all_pwd.txt')
    # {'dream': {'pwd': '521'}, 'user': {'pwd': '001'}}
    if username not in data_dict:
        return False, f"用户名尚未注册!"
    if password != data_dict[username]['pwd']:
        return False, f"密码错误！"
    else:
        txt = f"{username}登录成功"
        save_flow('save', user=username,
                  txt=f"{txt}>>>时间为>>>{datetime.now().strftime('%Y年%m月%d日 %H时%M分%S秒')}")
        return True, txt


def save_flow(state, user, txt):
    try:
        if state == 'save':
            with open(f'{ABSOLUTE_PATH}{user}_flow.txt', 'a', encoding='utf8') as fp:
                fp.write(txt + '\n')
        elif state == 'read':
            with open(f'{ABSOLUTE_PATH}{user}_flow.txt', 'r', encoding='utf8') as fp:
                return fp.read()
    except Exception as e:
        return f"文件写入/读取失败，错误信息为{e}"


# 验证是否登录的装饰器
def auth_login(func):
    def inner(*args, **kwargs):
        if not login_user_dict['username']:
            return False, '请先登录！'
        else:
            return func(*args, **kwargs)

    return inner


def func_choice(tag):
    def wrapper(func):
        def inner(*args, **kwargs):
            data = read_data('info', 'all_info.txt')
            user_dict = data[login_user_dict['username']]
            while True:
                bank_id = input("请输入银行卡号:").strip()  # 判断银行卡号是否为登录用户的
                if bank_id != login_user_dict['bank_id'] and tag != 'transfer':
                    return False, "银行卡号与当前登录用户卡号不相符，请选择转账功能！"
                elif tag == 'transfer' and bank_id not in [value['id'] for key, value in data.items()]:
                    return False, "对方尚未注册该银行卡号！请提示对方进行注册！"
                elif tag == 'withdraw' and bank_id != login_user_dict['bank_id']:
                    return False, f"卡号{bank_id},输入有误，请检查"
                balance = input("请输入金额:").strip()  # 判断金额是否符合格式
                if not balance.isdigit():
                    print(f"请不要输入非法字符，非法输入:{balance}")
                    continue
                balance = int(balance)
                if balance < 0:
                    print("不可以输入负数！")
                elif tag != 'recharge' and balance > user_dict['balance']:
                    print("余额不足！")
                    continue
                if tag != 'recharge':
                    count = 1
                    while True:
                        for_pay_pwd = input("请输入取款密码:")
                        if for_pay_pwd == login_user_dict['bank_pay_pwd']:
                            break
                        elif count == 4:
                            print("密码错误次数已达上限，请重新选择！")
                            break
                        else:
                            print(f"密码错误({count}/3次机会)")
                            count += 1
                            continue

                return func(balance=balance, bank_id=bank_id)

        return inner

    return wrapper


@auth_login
@func_choice('withdraw')
def withdraw_money(*args, **kwargs):  # 取款
    data = read_data('info', 'all_info.txt')
    balance = kwargs.get('balance')
    user_new_balance = login_user_dict['balance'] - balance
    user_data = data[login_user_dict['username']]
    user_data['balance'] = user_new_balance
    flag, msg = save_data('info', username=login_user_dict['username'], **user_data)
    if flag:
        txt = f"{login_user_dict['username']}取款{balance}元成功"
        save_flow('save', user=login_user_dict['username'],
                  txt=f"{txt}>>>时间为>>>{datetime.now().strftime('%Y年%m月%d日 %H时%M分%S秒')}")
        return flag, txt
    else:
        return flag, msg


@auth_login
@func_choice('transfer')
def transfer_money(*args, **kwargs):  # 转账
    data = read_data('info', 'all_info.txt')
    balance = kwargs.get('balance')   # 转账金额
    for_bank_id = kwargs.get('bank_id')   # 收集到转账银行卡号
    user_new_balance = login_user_dict['balance'] - balance   # 所剩余额
    pay_dict={'id':login_user_dict['bank_id'],'pay_pwd':login_user_dict['bank_pay_pwd'],'balance':user_new_balance}
    save_data('info',username=login_user_dict['username'],**pay_dict)
    payee_dict = {}   # 收款人信息
    username = ''   # 收款人姓名
    for key, value in data.items():
        if for_bank_id == value['id']:
            username = key
            payee_dict[key] = value
    payee_dict[username]['balance'] += balance
    save_info = payee_dict[username]
    flag, msg = save_data('info', username=username, **save_info)
    if flag:
        txt = f"{login_user_dict['username']}成功转账给{username}>>>{balance}元"
        save_flow('save', user=login_user_dict['username'],
                  txt=f"{txt},时间为>>>{datetime.now().strftime('%Y年%m月%d日 %H时%M分%S秒')}")
        save_flow('save', user=username, txt=f"{txt},时间为>>>{datetime.now().strftime('%Y年%m月%d日 %H时%M分%S秒')}")
        return flag, txt
    else:
        return flag, msg


@auth_login
@func_choice('recharge')
def recharge(*args, **kwargs):  # 充值
    check_login()
    data = read_data('info', 'all_info.txt')
    balance = kwargs.get('balance')
    user_new_balance = login_user_dict['balance'] + balance
    user_data = data[login_user_dict['username']]
    user_data['balance'] = user_new_balance
    flag, msg = save_data('info', username=login_user_dict['username'], **user_data)
    if flag:
        txt = f"充值{balance}元成功"
        save_flow('save', user=login_user_dict['username'],
                  txt=f"{txt}>>>时间为>>>{datetime.now().strftime('%Y年%m月%d日 %H时%M分%S秒')}")
        return flag, txt
    else:
        return flag, msg


def check_flow():  # 查看余额
    check_login()
    data_dict = read_data('info', 'all_info.txt')
    balance = data_dict[login_user_dict['username']]['balance']
    return True, f"当前登录用户{login_user_dict['username']}，还剩余额{balance}"


def bank_info():  # 卡号，余额，流水
    flow = save_flow('read', login_user_dict['username'], '')
    msg = f'''
    当前登录用户{login_user_dict['username']}信息如下
    卡号:{login_user_dict['bank_id']}
    余额:{login_user_dict['balance']}
    流水如下：\n
{flow}'''
    return True, msg


def quit_system():
    return False, 'break'


func_menu = '''
===================用户功能菜单=====================
                  1.注册
                  2.登陆
                  3.取款
                  4.转账
                  5.充值余额
                  6.查看余额
                  7.查看银行信息(查看自己的卡号、余额、流水等信息)
                  8.退出系统
======================欢迎使用=======================
'''
func_dict = {
    1: register,
    2: login,
    3: withdraw_money,
    4: transfer_money,
    5: recharge,
    6: check_flow,
    7: bank_info,
    8: quit_system
}


def main_system():
    # 【1】打印功能菜单
    while True:
        print(func_menu)
        func_id = input("请输入功能ID :>>>> ").strip()
        if not func_id.isdigit():
            print(f'{func_id} :>>>> 非法字符')
            continue
        func_id = int(func_id)
        if func_id not in func_dict.keys():
            print(f"{func_id} :>>>> 不存在该功能!")
            continue
        func = func_dict.get(func_id)
        flag, msg = func()
        if flag:
            print(msg)
        elif not flag and msg == 'break':
            print(f"欢迎下次使用!再见!")
            break
        else:
            print(msg)
            continue


main_system()
